---
title: Passing arguments to your requests
version: 1
---

import { Link } from "../../src/components/Link";
import { AutoSnippet, When } from "../../src/components/CodeSnippet";
import noArgProvider from "./passing_args/no_arg_provider";
import family from "!!raw-loader!./passing_args/raw/family.dart";
import codegenFamily from "!!raw-loader!./passing_args/codegen/family.dart";
import consumerProvider from "!!raw-loader!./passing_args/raw/consumer_provider.dart";
import consumerFamily from "!!raw-loader!./passing_args/raw/consumer_family.dart";
import consumerListFamily from "!!raw-loader!./passing_args/raw/consumer_list_family.dart";
import multipleConsumerFamily from "!!raw-loader!./passing_args/raw/multiple_consumer_family.dart";
import tupleFamily from "!!raw-loader!./passing_args/raw/tuple_family.dart";
import consumerTupleFamily from "!!raw-loader!./passing_args/raw/consumer_tuple_family.dart";

In a previous article, we saw how we could define a "provider" to make
a simple _GET_ HTTP request.  
But often, HTTP requests depend on external parameters.

For example, previously we used the [Bored API](https://boredapi.com/)
to suggest a random activity to users.
But maybe users would want to filter the type of activity they want to do,
or have price requirements, etc...  
These parameters are not known in advance. So we need a way to pass
these parameters from our UI to our providers.

## Updating our providers to accept arguments

As a reminder, previously we defined our provider like this:

<AutoSnippet {...noArgProvider} />

<When codegen={false}>

When not relying on code-generation, we need to tweak the syntax for defining
our providers a bit to support passing arguments. This is done by relying on
the "modifier" called "family".

In short, we need to add `.family` after the type of our provider, and
an extra type parameter corresponding to the argument type.
For example, we could update our provider to accept a `String` argument
corresponding to the type of activity desired:

<AutoSnippet raw={family} />

</When>

<When codegen={true}>

To pass parameters to our providers, we can simply add our parameters
on the annotated function itself.  
For example, we could update our provider to accept a `String` argument
corresponding to the type of activity desired:

<AutoSnippet raw={codegenFamily} />

</When>

:::caution
When passing arguments to providers, it is highly encouraged to
enable "autoDispose" on the provider.  
Failing to do so may result in memory leaks.  
See <Link documentID="essentials/auto_dispose" /> for more details.
:::

## Updating our UI to pass arguments

Previously, widgets consumed our provider like this:

<AutoSnippet raw={consumerProvider} />

But now that our provider receives arguments, the syntax to consume it is slightly
different. The provider is now a function, which needs to be invoked with the parameters
requested.  
We could update our UI to pass a hard-coded type of activity like this:

<AutoSnippet raw={consumerFamily} />

<When codegen={true}>

The parameters passed to the provider corresponds to the parameters
of the annotated function, minus the "ref" parameter.

</When>

:::info
It is entirely possible to listen to the same provider with different arguments
simultaneously.  
For example, our UI could render both "recreational" _and_ "cooking" activities:

<AutoSnippet raw={multipleConsumerFamily} />

<When codegen={false}>

This is the reason why the modifier is called "family": Because passing
parameters to a provider effectively transforms the provider in a group of
states with the same logic under the hood.

</When>
:::

## Caching considerations and parameter restrictions

When passing parameters to providers, the computation is still cached.
The difference is that the computation is now cached per-argument.

This means that if two widgets consumes the same provider with the same
parameters, only a single network request will be made.  
But if two widgets consumes the same provider with different parameters,
two network requests will be made.

For this to work, Riverpod relies on the `==` operator of the parameters.  
As such, it is important that the parameters passed to the provider
have consistent equality.

:::caution
A common mistake is to directly instantiate a new object as the parameter
of a provider, when that object does not override `==`.  
For example, you may be tempted to pass a `List` like so:

<AutoSnippet raw={consumerListFamily} />

The problem with this code is that `['recreational', 'cooking'] == ['recreational', 'cooking']` is `false`.
As such, Riverpod will consider that the two parameters are different,
and attempt to make a new network request.  
This would result in an infinite loop of network requests, permanently
showing a progress indicator to the user.

To fix this, you could either use a `const` list (`const ['recreational', 'cooking']`)
or use a custom list implementation that overrides `==`.

To help spot this mistake, it is recommended to use the [riverpod_lint](https://pub.dev/packages/riverpod_lint)
and enable the [provider_parameters](https://github.com/rrousselGit/riverpod/tree/master/packages/riverpod_lint#provider_parameters)
lint rule. Then, the previous snippet would show a warning.
See <Link documentID="introduction/getting_started" hash="enabling-riverpod_lintcustom_lint" /> for installation steps.
:::

<When codegen={false}>

With that in mind, you may wonder how to pass multiple parameters to a provider.  
The recommended solution is either to:

- Switch to code-generation, which enables passing any number of parameters
- Use Dart 3's records

The reason why Dart 3's records come in handy is because they
naturally override `==` and have a convenient syntax.  
As an example, we could update our provider to accept both a type of activity
and a maximum price:

<AutoSnippet raw={tupleFamily} />

We can then consume this provider like so:

<AutoSnippet raw={consumerTupleFamily} />

</When>
